/*  
  -- The Lime II Project -- 

  A tuplespaces-based middleware for coordinating agents and mobile hosts.
  Copyright (C) 2005.
  Gian Pietro Picco, Amy L. Murphy, Lorenzo Bellini.

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  Lesser General Public License for more details.

  You should have received this copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
*/

package lime2;
import lights.interfaces.*;

/**
 * Models a reaction. Application programmers must be very careful about consequences of the behavior they are trying 
 * to implement. Badly written reactions or unexpected interactions between reactions can make the (whole) Lime system
 * to loop: i.e., a a once-per-tuple reaction that "outs" a new tuple for every new tuple that is "outed" in the 
 * tuplespace.
 * <br>
 * Please note that the public constructor of Reaction performs parameter checking.
 * 
 * @author Gian Pietro Picco
 * @author Amy Murphy
 * @author Lorenzo Bellini
 */

public class Reaction implements java.io.Serializable
{
 /** 
  * The reaction is fired once and then it is removed automatically from the reactive program.
  */
 public static final byte ONCE = 1;

 /** 
  * The reaction is fired, and will never fire again for that given tuple, but remains registered. 
  * So, if multiple tuples enable the reaction, the reaction is fired for each of them. 
  */
 public static final byte ONCEPERTUPLE = 2;
 
 //is it a once or once-per-tuple reaction ?
 private byte mode;

 // the reaction listener of this reaction
 private ReactionListener listener;

 // the template that triggers the firing of this reaction
 private ITuple template;

 /**
  * Constructor method. Performs parameter checking.
  * 
  * @param mode Reaction.ONCE or Reaction.ONCEPERTUPLE
  * @param limetemplate the template that triggers the firing of this reaction
  * @param listener the listener which is invoked on firing
  */
 public Reaction(byte mode, LimeTemplate limetemplate, ReactionListener listener)
 {
  // parameter checking
  if (((mode != ONCE) && (mode != ONCEPERTUPLE)) || limetemplate == null || listener == null) throw new IllegalArgumentException("invalid/null value"); 	
 	
  this.mode = mode;
  this.template	= limetemplate.limify();
  this.listener = listener;
 }

 /**
  * Constructor method (package-only visible).
  * 
  * @param mode Reaction.ONCE or Reaction.ONCEPERTUPLE
  * @param template the "limified" ITuple that triggers the firing of this reaction
  * @param listener the listener which is invoked on firing
  */
 Reaction(byte mode, ITuple template, ReactionListener listener)
 {
  this.mode = mode;
  this.template	= template;
  this.listener = listener;
 }

 /**
  * Returns the firing mode. 
  * 
  * @return Reaction.ONCE or Reaction.ONCEPERTUPLE
  */
 public byte getMode()
 {
  return mode;	
 }
 
 /**
  * Returns the template (in form of ITuple) that triggers the firing of this reaction. 
  * 
  * @return template ITuple
  */
 ITuple getTemplate()
 {
  return template;
 } 
 
 /**
  * Returns the template (in form of LimeTemplate) that triggers the firing of this reaction.
  * 
  * @return template LimeTemplate
  */
 public LimeTemplate getLimeTemplate()
 {
  return LimeTemplate.delimify(template);
 }
 
 /**
  * Returns the listener associated with this reaction.
  * 
  * @return ReactionListener
  */
 public ReactionListener getListener()
 {
  return listener;	
 }

 /**
  * toString method.
  * 
  * @return textual representation of a reaction
  */ 
 public String toString() 
 {
  String msg = "[Reaction] mode=";
  switch (mode) 
  {
   case ONCE: msg = msg + "ONCE"; break;
   case ONCEPERTUPLE: msg = msg + "ONCEPERTUPLE"; break;
  }
  return msg + " template=" + template + " listener=" + listener.getClass().getName();
 }
 
}
